masterofmagicfandomcom-20200216-history
User talk:SeravySensei
Archived discussions Hello from Beastorizer Hi Seravy. Your work on the 1.5 patch and Caster of Magic is much appreciated. I actually don't mind the new cameos, I figure I've got enough openness to experience to play 25 yr old DOS games so anime is no big deal. It's not even that weird, there is a nude pokemon total conversion mod for Sid Meier's Alpha Centauri after all. However, I've only watched ~20 anime in my time so I'm unable to recognize all these new characters. Would you mind making a list of: anime girl > MOM character they replace > what anime/game they are from Also, of the source anime which do you recommend watching? Thanks, Beastorizer (talk) 05:16, April 10, 2019 (UTC) Raise Dead Sorry, I'm opening this can of worms, but there's been way too many changes to the Raise Dead spell-cast function by both you and kyrub to make it viable for me to create a universal fix. So here's the list of issues, their current workarounds in the RC/CoM, if any, what I'd consider to be the proper solutions, and my comments: # The target array size is limited to 8. If there are more, we start overwriting stuff. Even in v1.31, you can get 9 targets here, so this is most certainly a problem. It is also untouched as of yet. The question is, how many targets should be allowed? The obvious answer is 36 + 1 (I'll get back to that in a minute), except that yields 37 * 2 * 2 = 148 bytes (2 word-sized arrays, one for the indices, one for the string pointers), which need an extra byte to address. For v1.31, I'll go for 16, would that be enough for you? # The strings in the string pointer array are being copied to instead of assigned to, leading to automatic memory corruption every time the spell is cast. Kyrub did an utterly horrible fix of this 6-byte problem by redirecting the strings to the area of the data segment that holds the sound error messages. Even if by some miracle you convinced me to let that slip, extending the array will overwrite the _atexitcnt static of borland, which will crash the game whenever you exit (including to MAGIC.EXE). Unfortunately, I think the space kyrub freed during this fix are being reused in one of yours dealing with un-involved units, but I might be mistaken there. # Un-involved units are considered valid targets. This was supposed to be a one-byte fix, the one I posted earlier, which you've also used everywhere else, except here. It makes adding the second check specifically for status 3 units redundant. # The string list parameter of the GUI_ListSelect_Dlg function expects the list to be terminated by a zero string, an issue that can cause extra buttons to appear on the list that, when clicked, will crash the game more often than not. This is where the +1 above comes from, although technically the index array doesn't need this. On the other hand, it needs to be dynamically set up, for which the best space I found is the branch just before the call. # Casting the spell causes the graphics to get distorted by replacing the original combat background screen image with the full combat screen image, which is then used until reset way out in the main combat function. You've created a partial fix for this by removing the call that saves the full image over the background one, but that only fixes the problem if the selection list is never shown, as it will do this again regardless. The proper fix here is to recompose the background image afterwards, which is something the dialog itself can not do, as it is also used for overland spells. We can do it very easily however, without even altering the relocation table. # The list selection dialog loads its control images into a memory area that is no longer valid after returning, causing the game to crash on the next page flip if the GUI is not cleared beforehand (by the way, this is the same issue that causes the Call Chaos AI-cast crash in v1.31 - you'll probably hate me for undoing your new graphics in the next few weeks, but I'll try to give you something special to compensate for that). Your current workaround is to just use the function without the scrolling capability. This is enough for displaying 10 units or so without breaking the graphics and possibly messing up the return value. This bug is easy to fix in the dialog function itself, which will automatically apply to all of the spells using it. Of course, in the end, you can decide to just leave everything as it is, it's a more or less valid standpoint, as the major crash bugs are fixed one way or another. Your AI target selector filters out the AI side bugs, which really leaves only the ones where the human player has a long list of units to raise. Also, this does not yet touch on Animate Dead, apart from fixing the dialog used by both. Do you want me to check which of these can be universally fixed and continue from there, create a small reversal patch and fix everything from the v1.31 code, or try to create a special version with only the fixes of your choice? My original fix for all of these involves around 45 bytes in the Raise Dead function and around 30 in the dialog. As far as I could tell the CoM and the RC code is the same in both regions, the AI target selection is resolved elsewhere and inserted into the tile randomizer space, so with a minimal reversal, I think nothing should be in the way. Drake178 (talk) 01:09, July 10, 2019 (UTC) 1. Actually the (not so) obvious answer is 9. Raise Dead targets self-owned normal units and you can at most have 9 of those, the rest of the slots can only ever have combat summons in them or belong to the enemy. This is true even for CoM in theory although I'm not sure I ever tested if the combat summoned "normal turned fantasic" units are properly excluded, they should be. This won't be so trivial for Animate Dead though which raises enemy and fantastic units as well. Also unsure what happens if a control changed unit dies, that might make it possible to have 18 valid targets instead of 9 if they stay on the new owner's side of the "graveyard". So 18 should be the 100% safe amount but I can't really imagine a combat where I possess 8 or more enemy units, they all die, and I'm STILL fighting that battle without either side winning AND Cast Raise Dead on top of it. (In fact you need the life+death mod to even do that unless all units died when confusion made them randomly change sides.) So I think 16 is good enough for this but Animate Dead will be different. 2. Yeah that sounds bad, it should be fixed. 3. I do have "3" excluded specifically in CoM, yes, doing >3 like you did it better. It probably ended this way because I copied the exclusion of 6 without noticing it already has a >0 earlier or maybe didn't know what 1 and 2 were for at that time. 6. Not really, I don't care much for the "new graphics" it was just a workaround for not being able to make the official one work. I admit I got used to it and it doesn't look bad at all, but it wasn't meant to be an important addition original. Looking forward to your alternate solution. As a side note, CoM's Call Chaos can't do "no effect", but can do "Confusion" instead so it is different. Another side note, in CoM in the "effect" part there are changes like zeroing more stuff on the raised unit, but those areas are likely not affected. I'd prefer one big patch file for all of this asuming you do want to spend time on fixing them all. I'll probably just write "fixes 6 different sources of crashes, memory or graphical corruptions in Raise Dead" in the patch file instead of trying to explain all that to users. But while we are at it, I have three more worms in the can left : 7. Raise Dead targets a random tile. I might like it this way better as it is more balanced for gameplay, but from a certain viewpoint this can be considered a bug? Is there any official source stating these revival spells cannot target a specific tile and also do not raise the dead unit where it actually died? Because one of those two would make sense, this does not and is unique, the only other thing that does it is Summon Demon which is an ability, not a spell at least in the RC. (random is good for game balance because it means you can't raise a unit and suicide it on a target to deal massive damage immediately the repeat - unless it can move a lot or have teleport or merging items in which case you can nonetheless. But it's not a big concern because CoM limits raising the same unit to only once per combat anyway.) 8. If you click outside the menu to cancel the spell, the cost is used up. This is unlike any other combat spell where cancelling without selecting a target spends nothing. Probably hard to fix but has actual unwanted game consequences if someone triggers it, and the worst part is, they might not even know clicking there cancels the spell, and it's fairly easy to do so by accident. 9. What happens to the movement of the unit? As far as I remember, the spell raises the unit with full movement but when I did the big CoM movement overhaul last week I didn't find where the movement is reset and I also don't think dead units reset it at end of turns. I'm not even sure what should happen? Get back the unit with the amount of moves it had left, but full if it died in an earlier turn, or have it at full even if it did move, die and revive in one turn? The CoM movement overhaul now resets it just to be on the safe side but no idea about the original. SeravySensei (talk) 02:11, July 10, 2019 (UTC) :7 and 8 are on my other list, because I can't immediately fix them from where I am. There is nothing in either the Spellbook supplement or the Official Strategy Guide that either explains, or even mentions the different targeting of these spells. It was also marked as a "bug" by Nodemaster, one of the contributors to the original gamefaqs guide, although I relegated it to a concept flaw instead. However, to be perfectly honest, I have a bit of a vision here, that if I can realize, I actually wouldn't care what the "canon" was in this particular case. :So here's what I imagined. You cast Raise Dead or Animate Dead. A shadow is cast over the battlefield, everything freezes, and the dead units that are valid targets suddenly appear as "spirits" of their former selves - mostly blue, but some of them red. This is your target picker. You can mouse over the units to get a tooltip, and if I'm really good, you may even be able to right-click them for stats (but I can't promise this one). For Raise Dead, multi-figure units appear with half the figures, as they would if brought back. :If you click on a blue unit, targeting is finished, the unit comes back on the tile it is on, and combat resumes. If you click on a red unit, you get a warning that the tile it died on is occupied, and if targeted, the unit will come back to a random tile, with a dialog asking if you wish to continue. You can then select "Yes", in which case the unit is summoned to a random tile, or "No" to get back to the target picker. You can also "Cancel" at the bottom right to exit without spending resources. :Now this may seem like it's outside the realm of possibility to you, but it isn't at all, the hardest part most likely being choosing (or creating) the right image effect (BU field 0x60 IIRC) for the spirits. For the rest, I just need some space, two or three functions, and a bunch of far calls. Implementing this would resolve both 7 and 8 in a very novel way, but it's unfortunately not something I can do until later on, so a temporary solution may be warranted in the meantime. :Which brings us to the random summoning. Since this would be required anyway, and because it's also used in other places, I'll probably start here as soon as I get to a state where I can tackle this issue. You see, this is also inherently bugged everywhere it is done. If all of the tiles in the 3×3 are occupied by units already, one of two things will happen. Half of the functions that use this feature will pop a unit on top of another one that's already there, while the other half will simply freeze in an infinite loop. :I would most certainly not want to fix this everywhere it occurs. It is much more desirable to create a separate function that takes an X and a Y return pointer along with a boolean for attacker/defender, and resolves the tile picking randomly if possible, or by, say, clockwise extension from the center if not. Or a 4×4 random. Or any other reasonable method that always yields a valid result. This function could then be called from all of the places where a random summon occurs. :The reason I didn't do anything about this yet is that I still don't have all the uses of the targeting map in sight, which is what all of these code blocks depend on. I know where and how it's filled out, but I don't know all of the whens, and there is also some contradicting stuff about the how. I'm reluctant to try to fix something when I can't see the whole picture yet. :Anyway, assume we go with the random for Raise Dead rather than the tile select for Animate Dead. At least, that would be my choice despite the little player ringing in my ear telling me that's the worse one. That means that for a start, the resolution of these spells should be altered. Namely, the selection should be performed when other spells do their target picking, and the actual spell-cast routine should only execute the animation and apply the effect. This way, it's the list selection that is cancelled during target picking, which yields a -1 in the main combat spell function, which resolves #8 automatically. :Since both spells have a separate function, we can probably reorganize them such that one will be the target picker for both, the other the execution for both. Otherwise, we have to build one or the other functionality into the existing combat spell routines. The ccc patch would probably allow this for the target picker in the RC through its combination of the resource expenditure branches, which should actually also be portable to CoM. However, separate functions would ultimately be desirable, especially if the first solution is going to be a temporary one for sure. :As for 9, I'll see if I can find that, I don't know off the top of my head either. EDIT: BU_SetBaseStats(), the generic stat (re-)calculator sets movement at $8F2B2. So it's always full movement. Drake178 (talk) 20:12, July 10, 2019 (UTC) : I should have realized but it's so counterintuitive my mind completely ignored that even though I had to disable it when fixing movement in CoM. I thought "that can't be there, it would reset the movement in the middle of the turn if the unit is ever recalculated" and that's exactly what it did in the CoM update at first. But in the original it's safe, but only because ALL stat recalculations also save and then restore the movement. SeravySensei (talk) 14:22, July 11, 2019 (UTC) Enchant Target Picker Yes, this is already excluded in CoM in the $81810 function. However 1.51 seems to have an older version of it which doesn't include magic immunty checks yet. I suggest modifying the CoM version of that procedure for compatibility (the issue is CoM has some spells added or removed, it isn't the space), this is the latest CoM source - do note due to space limitations, there might still be some restrictions implemented outside or not at all, but it at least covers most stuff : I'll fix the outside having 20h instead of the correct 8 for magic immunity enchantment, and I'd prefer if the check for the unit ability was done inside as it affects a lot more spells. ; in : ; di = battle unit ID ; bp+6 spell id ; bp-0Ah enchantments low ; bp-0Ch enchantments high ; out : ; dx = priority ; * 81810 ;------------------------------------------------- ; Prepare data ;------------------------------------------------- push si mov si,bp+6 ; si = spell mov ax,di mov dx, 6Eh ; 'n' imul dx les bx, 922Ah add bx, ax ; es:bx = unit offset test word ptr es:bx+22h,442h jnz invalid xor dx,dx ; return value = 0 ;------------------------------------------------- ; Gate Bonus ;------------------------------------------------- cmp word ptr es:bx+44h,8 jnz skip cmp word ptr es:bx+46h,12 jnz skip add dx,20 ; +20 to unit at gate skip: ;------------------------------------------------- ; Which spell? ;------------------------------------------------- ; Resist Elements cmp si,2 jz magimmun ; Don't if Magic Immunity ; Elemental Armor cmp si,15h jz magimmun ; Don't if Magic Immunity ; Iron Skin ;cmp si,18h ;jz prefhero ; Regeneration cmp si,1Fh jz regen ; Resist Magic cmp si,29h jz magimmun ; Don't if Magic Immunity ; Guardian Wind cmp si,2Ch jz guardian ; Flight cmp si,38h jz strongest ; Invisibility cmp si,3Eh jz prefranged ; Magic Immunity cmp si,45h jz magimmun ; Haste cmp si,4Dh jz strongest ; Eldritch Weapon cmp si,5Eh jz strongest ; Flame Blade cmp si,56h jz atkbuff ; Immolation cmp si,63h jz maxdef ;immolate ; Bless cmp si,79h jz magimmun ; Holy Weapon cmp si,7Ch jz atkbuff ; Holy Armor cmp si,7Eh jz maxdef ; Heroism cmp si,82h jz heroism ; True Sight cmp si,83h ; Don't if already Illusion Immune (no space) jz prefranged ; Lionheart ;cmp si,8Dh ;jz prefhero ; Invulnerability ;cmp si,8Fh ;jz prefhero ; Rightousness ;cmp si,90h ;jz prefhero ; Cloak of Fear ;cmp si,0A4h ;jz prefhero ; Berserk ;cmp si,0B3h ;jz berserk ; Wraith Form cmp si,0A8h jz wraithform jmp prefhero wraithform: test byte ptr es:bx+19h,1h jnz invalid ; Don't if already weapon immune! jmp prefhero ;immolate: ;NOT ENOGUH SPACE FOR THIS ;test byte ptr es:bx+1Ah,8h ;jnz invalid ; Don't if already immolating ;jmp maxdef regen: test byte ptr es:bx+1Dh,20h jnz invalid ; Don't if already regenerates jmp prefhero magimmun: test byte ptr es:bx+18h,20h jnz invalid ; Don't if already magic immune! jmp prefhero ;------------------------------------------------- heroism: mov ax, es:bx+30h mov cl, 5 shl ax, cl les bx, 9EC2h add bx, ax cmp es:bx+0Ch,2 ; only if level=0 or 1 jge invalid jmp strongest ;------------------------------------------------- ;bless: ;test bp-0Ah,4000h ; Not if Righteousness! ;jnz invalid ;jmp prefhero ;------------------------------------------------- maxdef: mov al, es:bx+5 cbw sal al,4 ; +16 point per defense add dx,ax jmp strongest ;------------------------------------------------- berserk: mov al, es:bx+5 cbw sal al,1 ; -2 point per defense add dx,ax neg dx ; Negate gate bonus as well atkbuff: mov al, es:bx ; melee mov bl, es:bx+0Dh ; figures imul bl ; highest melee*figure! add dx,ax jmp done ;------------------------------------------------- prefranged: mov al, es:bx+1 cbw sal al,4 ; +16 point per ranged attack strength add dx,ax jmp strongest ;------------------------------------------------- guardian: test byte ptr es:bx+18h,4 ; Missile Immunity jnz invalid prefhero: mov ax, es:bx+30h mov cl, 5 shl ax, cl les bx, 9EC2h add bx, ax ''cmp byte ptr bx+06h,0FFh ; shouldn't that be es:? <--------------------'' jle strongest add dx,60 ; +60 priority if hero strongest: push dx push di db 9Ah,2Ah,00,58h,04h pop cx pop dx add dx,ax jmp done invalid: mov dx,0FFC0h done: pop si retn Edit : both immolation and true sight are already implemented outside in CoM but if you have the space you probably want it done inside for the RC. At first sight the most obvious differences seem the need to uncomment righteousness and berserk. Combat Spell Lock is not a thing in CoM, but it is in the RC for that you likely want the target with most existing enchantments. Everything else looks good as is. :Hey, it's the unused Disintegrate target picker! =P Questions, questions, questions. Whenever you have a few minutes =) # With Spell Lock, I'd assume the Gate Bonus shouldn't apply, but should targeting be based solely on the amount of enchantments and no other factors? I mean I could do something like 2 or 4 per enchant, maybe some extra for fantastic units if the opponent plays blue or white (not sure how I would query that yet though), but then branch into strongest too? Or would that create too much of a bias? I don't know how big the range of that evaluation result is. # Is the code I see in the executable a direct result of the above input into your assembler? Specifically, the "sal al, 4" turned into 4 consecutive "shl al, 1" instructions bothers me somewhat. # Do you want the above code to be a bit more optimized in terms of space, or are you happy with it as it is? # Do you want me to keep this setup for the RC or can I do some of the stuff from my previous question there? E.g., I found this to be a more optimal entry setup, and it would also work with your current CoM version because it no longer actually uses the enchant flags in this function, and there's enough space before both calls for setting ax: ; in : ; di = battle unit ID ; ax = spell id ; cx = enchantments low (don't need for CoM) ; dx = enchantments high (don't need for CoM) ; out : ; dx = priority On a side note, would you mind if I archived some of the older sections/headings of your talk page (i.e. move them to a separate page that I link to at the top)? Drake178 (talk) 21:22, July 7, 2019 (UTC) 1. Maybe looking at the overland version can give you some ideas, but that's about it, yes. Extra for fantastic units sounds good too, enemy realms are stored in $9298-92a2, see the function at $BBCCC which fills them. I'd scale this half of the priority based on the amount of resistance missing to be mostly invicible if there is room for that and the other half by number of enchants on the unit. I'd also consider things with not enough spells and not fantastic with vulnerable resistance an invalid target because it's a waste to cast it in that case. However this sum of priority would then be scaled (multipled) by the cost of the unit - it's meaningless to protect something that's not a relevant unit. Gate bonus should probably stay but only if the target is otherwise having a reasonable priority. Ultimately this is entirely up to how much effort you want to put into it, Spell Lock isn't exactly the most important or fun spells in the game. 2. Yes. (well, not the same version, the posted one is the newer CoM one) There is no shl al,4 instruction for the x86 CPU, only sal al,cl but that requires loading 4 into cl. I can't use that if I use cx. I don't think this is an assembler bug although I've seen it generate other bugs before (it doesn't like jumps over $8000 distance and pushing immediate bytes over $80, I think that's all I ever had problems with). ::Huh? Why would you be coding for a 8086 when the game requires a 386+? EDIT: oh my, that just made me realize why the borland compiler did it that way... Anyway, SHL AL, 4 (C0 E0 04) is perfectly valid from the 80286, and you're free to use it in your code. I know it works because I'm using SHL R16, IMM8 quite a lot, and that was introduced in the same processor. Both DOSBox and IDA understand it without issues. ::Drake178 (talk) 23:58, July 7, 2019 (UTC) ::It does? I don't remember seeing that in the game's readme files but ofc that doesn't mean it's not true. I saw no use of eax anywhere so I assumed it isn't for 386. I guess 286 is still a step above x86 though and that definitely is required due to memory, but I was happy to find any working assembler at all, even that took quite some searching around. Although considering everyone runs it on DOSBOX anyway, it's not like we do need to maintain 286 compability, not sure why I even cared. Then again, this is the only working assembler I found so... I didn't have much choices to think about so I never did. SeravySensei (talk) 00:30, July 8, 2019 (UTC) :Well, by the looks of it, the game was actually compiled with the default option of BC 3.1, which is to generate 8086 code. What a shame. The manual says on the first page that an 80386sx is required. Which kind of makes sense, since unless you had a hardware EMS board, you needed a 386 to have EMS. It doesn't matter that much though, with 16bit default addressing the only practical use of the 32bit registers that I see would be some bitflags, so an operand size prefix would probably not be worth the hassle. I'll stick with the 16bit code too, but things like the above SHL AL, 4 or, more importantly, an IMUL DI, 6Eh can be immensely useful =D Drake178 (talk) 01:17, July 8, 2019 (UTC) :EDIT: oh, for the record, I don't use an assembler, at least not the way you do. I just use this (that also messes up 16bit immediate pushes and long jumps by wanting to operand-size prefix them, so those I do manually). Drake178 (talk) 01:20, July 8, 2019 (UTC) 3. Up to you, I'm not modifying RC code myself unless it's exceptional, I only add the patches. If you think you are going to need the space in the future, sure, otherwise there is no point. 4. You can do it however you find more convenient as long as is functionally equivalent or preferably, superior. Sure, you can move them. This whole wiki talk stuff is kinda alien and chaotic to me, forum threads and posts make more sense then editing the same "post" for everything... SeravySensei (talk) 21:58, July 7, 2019 (UTC) 1.51 RCx Bugs and fixes =) :::The Maybe Batch :::Optionals :* Next one: Fixes bug: AI can waste Mana/Skill on Banish Because it's adjusting the extra to a random multiple of 5 instead of 15, which is what actually grants a benefit. Will produce a warning without W126, which it also functionally supercedes (can't reverse it any more, have to do so at $8367E instead of $8369E). v1.31 - v1.51 (WIZARDS.EXE) ; swap the Counter Magic and Banish checks 8367D 40 30 ; skip the first check instead of the second in v1.50+ ; (remove this one byte for a v1.31 patch) 8367E 75 EB ; swap the Counter Magic and Banish checks 8369D 30 40 8369E EB 75 ; use increments of 15 instead of 5 for Banish 836A3 05 0F 836B2 05 0F Drake178 (talk) 17:17, June 18, 2019 (UTC) For this one, we probably should make the AI spend the optimal amount instead of at random? No idea how much that is though, slider spells are not really a thing in CoM. But it should depend on the effective resistance of the target against the spell. It should lean towards spending more for a "faster" success but should avoid wasteful spending (Definitely avoid over 100%, boost below 50%, not sure in-between though). SeravySensei (talk) 15:06, July 4, 2019 (UTC) :I'll do some brainstorming on this, I've made loads of placeholder far calls and an extreme amount of space in that function, so anything goes really. Might check if I can retrieve the result of the original target picker that resulted in the spell being selected, or more likely just redo it and base a decision on that. In that case though, it may be worth doing the same for some other slider spells too, like Life Drain and direct damage. Drake178 (talk) 22:08, July 6, 2019 (UTC) :* Next one: Fixes bug: control changed heroes check the wrong records for hero spells AI side for CoM only. CoM only (WIZARDS.EXE) ; mov bl, es:bx+3 BC3EE 90 26 BC3EF 90 8A BC3F0 90 5F BC3F1 90 03 ; xor bh, bh (replacing mov bx, bp-2) BC3FD 8B 30 BC3FE 5E FF BC3FF FE 90 Drake178 (talk) 22:08, July 6, 2019 (UTC) Added to my CoM files, thanks! Also finished implementing the movement stuff yesterday, it took the whole day but it works. Next CoM version won't be up for download for a while though, I'll be starting a new test game soon. It's way too many changes to release untested, there might be some more movement spells lurking around I forgot about or something. Also need to decide how to update the treasure generation to avoid the Myrran plane getting too much book/retort treasure as it all ends up on that one player there. Last game the Myrran found 6 of them, was really broken. SeravySensei (talk) 22:51, July 6, 2019 (UTC) :* Next one: Well, if you're playing... It's dangerous alone, take this with you! ;-) It's posted separately because of its size. By itself, this patch does the following: UI feature: combat spell targeting now also highlights the target tile for non-unit spells, if it is valid for the spell being cast UI feature: combat spell targeting has greatly improved responsiveness In addition, it fixes the cursor side of the following issues. Some of the issues themselves have been fixed in the RC or in CoM. However, the cursor side has not been fixed for any of them yet in any version (contrary to common belief), so here you go. Don't forget the CoM supplement! There's also over 100 bytes left in total in case you want to add something. The new branching should make things fairly trivial. "Wrack entity" crash bug (active Wall Crusher vs BU index #99 vs active Wrack) Summoning spells, Magic Vortex, Cracks Call, and Earth to Mud can be cast on tiles outside of the valid playfield Summoning Spells can be cast on wall corners and central structures Magic Vortex can be cast on central structures Possession can be cast on Heroes Drake178 (talk) 23:27, July 6, 2019 (UTC) :* Next one: Fixes bug: the human player use Raise Dead on recalled units So long as they have at least one dead unit to cast the spell in the first place. v1.31 - v1.51 (WIZARDS.EXE) ; non-dead units fix AB08E 00 03 Drake178 (talk) 23:27, July 9, 2019 (UTC) :* Next one: Fixes bug: spells that use a list selector crash if they have over 6 valid targets. For the time being, this applies to Resurrection and, from what I've seen, Spell Binding in CoM. This fix is universal, so I've separated it out accordingly. It works by skipping the re-creation of the selection controls after clearing the GUI if a target is already picked. This means there are no graphical controls to redraw, the sandbox is safe to reload from EMM, and the page can be flipped without any further changes anywhere else. All versions (WIZARDS.EXE) ; list selection arrow button redraw fix CFB28 C7 B8 CFB29 46 18 CFB2A FC FC CFB2B 18 89 CFB2C FC 46 CFB2D C7 FC CFB2E 46 89 CFB2F FA 46 CFB30 18 FA CFB31 FC B9 CFB32 33 0A CFB33 F6 00 CFB34 EB BF CFB35 0B A0 CFB36 8B CA CFB37 DE 1E CFB38 D1 07 CFB39 E3 FC CFB3A C7 F3 CFB3B 87 AB CFB3C A0 83 CFB3D CA 7E CFB3E 18 FE CFB3F FC 00 CFB40 46 0F CFB41 83 85 CFB42 FE 23 CFB43 0A 02 CFB44 7C 90 CFB45 F0 90 Code: $CFB28: b8 18 fc mov ax, -1000 89 46 fc mov bp-4, ax 89 46 fa mov bp-6, ax b9 0a 00 mov cx, 10 bf a0 ca mov di, 0xcaa0 1e push ds 07 pop es fc cld f3 ab rep stosw 83 7e fe 00 cmp bp-2, 0 0f 85 .. .. jnz $CFD67 Drake178 (talk) 00:38, July 11, 2019 (UTC) :* Next one: Fixes graphical bug: rocks are drawn over single figure units in battle This was a really odd one. The game uses three different ways of setting up and querying in-tile coordinates. The functions that generate pixel coordinates use a grid of 8-by-8 per tile. These are used by pretty much every function that wants to draw something on a tile in combat, like spell animations, but also by the rock generator. Then there is the figure drawing, which arranges the figures of a unit using pixel coordinates directly instead of in-tile ones. Finally, there's the Z-depth calculator, which breaks down the pixel coordinates into a more precise 16-by-16 in-tile grid... Anyway, I think I managed to come up with a solution that creates the rocks in a way that a) they are always behind the single figure, b) not always behind every figure in a multi-figure unit and, most importantly, c) are still drawn on the tile they are on, instead of one to the left, right, or diagonally up. Because they affect movement, this last one was crucial, yet was probably the most difficult part of this exercise. Credit goes to you by the way, this was all done in CoM, because Construct Catapult made it ludicrously easy to test. Mind you, there may be a few types of rocks that I missed (I tested on 3 different maps), so if anything stands out while playing, let me know, and we can tweak it further. The one thing I can't really resolve is that when moving over the rocks, they will still be drawn in front of the figure as soon as their Z-depth (based on the bottom center'ish of both sprites) becomes smaller. Unfortunately, I also won't be able to use Z-depth for the Call Chaos animation (which is what I wanted to check here myself) - it's way too complicated to try and reverse-calculate the unit drawing order out of the combat entity table. Those records do have two empty fields though, so maybe another time, if I'm really bored and have nothing better to do, I may get back to that subject. All versions (WIZARDS.EXE) ; rock drawing Y image centering offset D665F 0C 0A ; rock generator in-tile X offset (added to a random(2)) D9E2C 03 01 ; rock generator in-tile Y offset (added to a random(2)) D9E3C 03 01 ; rock generator stored X pixel modifier ; (no clue why they've done this in the first place) D9FBD 05 90 D9FBE FB 90 D9FBF FF 90 No code, the first three are value adjustments, the last ones rip out an "add ax, -5". Drake178 (talk) 22:56, July 13, 2019 (UTC) :* Next one: (from blog post) Call Chaos no longer crashes the game when cast by the AI outside of the defender's first turn Call Chaos now uses the correct graphics for Doom Bolt and Fire Bolt Call Chaos no longer freezes all units while playing its animation Call Chaos no longer glitches the graphics when applying its effects Call Chaos now applies its effects with more appropriate timing The Healing animation of Call Chaos is no longer misaligned This turned out to be rather anti-climactic as far as the crash bug fix goes. I wrote a 4-byte fix for that several weeks ago already (2 different ones in fact), but unfortunately it wasn't a "proper" one in the sense that it looked like it might break one tiny piece of functionality on occasion, although I'm not actually sure that it would, since I'm not there in the code yet (this patch will never do that). Regardless, when I started preparing for this fix since I wanted to use the correct graphics anyway, I found, much to my dismay, that all of the animations combined, would still fit in the sandbox. Which means the devs introduced the crash bug for no reason whatsoever, simply because they failed to evaluate their own resources. Installing this will be somewhat complicated on your end. In the case of the RC, you'll need to apply the reverse patch first, then the patch itself (don't copy the two together). Like last time, you can choose to either keep W287 and W592 as Incompatible, or simply delete them from Included. For CoM, on the other hand, you'll need to install the patch first, and the extra file afterwards. There are two optionals that you can play around with if you want to, one restores the fire pillar animation of Flame Strike for the Fire Bolt effect, while the other swaps in a Disrupt animation for Warp Creature. Of course, you're free to pop in any other animation you want, just note that without dumping the sandbox to EMS, space is rather limited, and the aforementioned two won't even work at the same time. On the other hand, not using EMS meant that I could not only redraw the screen properly for each frame, but also apply the effects on the fly, when they are appropriate for the animation, rather than in one big loop halfway through. To this end, I changed the effect application function to no longer loop through the units, but instead take a unit index and an effect index and resolve just that one, since the looping is otherwise already implemented in the animation function. Because I assumed that your CoM Confusion effect will do the "random movement" on the spot, which would have broken the animation, I went ahead and worked around that, which will be something you need to keep in mind if you ever want to change that Confusion to ignore all immunities. How it works now, is that when the individual unit's effect animation reaches its last frame, the Confusion flag will be set on the unit immediately, but the effect is not applied yet. This is to ensure that the little blue stars keep circling around the unit's head for the entire Call Chaos animation, since Confusion is shorter than some of the rest. When the whole animation is over, and the memory allocated for it is released, the function will do another loop for only the Confusion effects, if any, and make the proper call to the effect application function, so they can be processed one after another. Although I did not get a random movement roll during my testing, I did get a unit switch sides immediately after casting the Apocalypse, so it seems to be working as intended. Which brings me to another thing, your alternate animation for this spell was in an area that is heavily modified in CoM, with jumps all over the place. The RC patches reversed made it fairly clear there, but in CoM, you should probably check that the pipeline still includes everything it should. I'm not worried about Call Chaos itself, but the rest of the spells that are animated by the same two combined functions. I did try to make sure I'm following up the jumps correctly after removing Call Chaos from the line, but it never hurts for someone more competent to double check. Which you typically are when it comes to CoM code. =D Drake178 (talk) 01:31, July 15, 2019 (UTC)